﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GnufBase.h"
#include "GnufImpl.h"

class QAbstractItemDelegate;
class QModelIndex;

namespace gnuf {
    
    class Item;
    class CustomizedDelegateBase;

    class GNUF_BASE_EXPORT ICustomizedDelegateHost : public gcmp::WeakReferenceable
    {
    public:
        ///\return Return the gnuf::Item at the model index.
        virtual const gnuf::Item * itemAtModelIndex(const QModelIndex &) const = 0;
        ///\brief Get the model index of the gnuf::Item.
        ///\return Return false if falied.
        virtual bool modelIndexOfItem(const Item *, QModelIndex &) const = 0;
    protected:
        void registerAtHost(CustomizedDelegateBase *);
    };
    
    class GNUF_BASE_EXPORT CustomizedDelegateBase
    {
    protected:
        explicit CustomizedDelegateBase();
        virtual ~CustomizedDelegateBase();
        
    public:
        ///\return Return the QAbstractItemDelegate.
        virtual QAbstractItemDelegate * asQAbstractItemDelegate() = 0;
        
        ///\return Return true if hosted.
        bool isDelegateHosted() const { return m_wpHost.IsValid(); }
        
        ///\return Return the host.
        ICustomizedDelegateHost * delegateHost()
        { return (m_wpHost.IsValid() ? m_wpHost.Get() : nullptr); }
        ///\return Return the host.
        const ICustomizedDelegateHost * delegateHost() const
        { return (m_wpHost.IsValid() ? m_wpHost.Get() : nullptr); }
        
    protected:
        friend class ICustomizedDelegateHost;
        gcmp::WeakPtr< ICustomizedDelegateHost > m_wpHost;
    };

    template <class TQtDelegate>
    class CustomizedDelegate
        : public TQtDelegate
        , public CustomizedDelegateBase
    {
        static_assert(std::is_base_of<QAbstractItemDelegate, TQtDelegate>::value,
            "TQtDelegate MUST be DERIVED from QAbstractItemDelegate!");
    public:
        explicit CustomizedDelegate() {}
        virtual ~CustomizedDelegate() {}
        
        // Inherits from CustomizedDelegateBase...
        virtual QAbstractItemDelegate * asQAbstractItemDelegate() override { return this; }
    };

}